package net.stogi.common.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import net.stogi.common.api.dto.OrderBy;
import net.stogi.common.dao.GenericDao;

import org.hibernate.LockMode;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

public abstract class GenericHibernateDaoImpl<E, ID extends Serializable> extends HibernateDaoSupport implements GenericDao<E, ID> {

	private Class<E> entityClazz;

	@SuppressWarnings("unchecked")
	public GenericHibernateDaoImpl(SessionFactory sessionFactory) {
		entityClazz = (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
		setSessionFactory(sessionFactory);
	}

	public void delete(E entity) {
		getHibernateTemplate().delete(entity);
	}

	public void evict(E entity) {
		getHibernateTemplate().evict(entity);
	}

	public List<E> loadAll() {
		return getHibernateTemplate().loadAll(entityClazz);
	}

	@SuppressWarnings("unchecked")
	public List<E> loadByExample(E exampleEntity) {
		return getHibernateTemplate().findByExample(exampleEntity);
	}

	public E loadById(ID id, boolean lock) {
		E entity;

		if (lock) {
			entity = getHibernateTemplate().get(entityClazz, id, LockMode.UPGRADE);
		}
		else {
			entity = getHibernateTemplate().get(entityClazz, id);
		}

		return entity;
	}

	public void save(E entity) {
		getHibernateTemplate().saveOrUpdate(entity);
	}

	protected DetachedCriteria addOrder(DetachedCriteria criteria, OrderBy... orderBy) {
		if (orderBy != null) {
			for (OrderBy o : orderBy) {
				if (o.isAscending()) {
					criteria.addOrder(Order.asc(o.getPropertyName()));
				}
				else {
					criteria.addOrder(Order.desc(o.getPropertyName()));
				}
			}
		}
		return criteria;
	}
}
